﻿namespace MyAbpCodeArtCore.Web.Tests
{
    using System;
    using System.Net;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Abp.AspNetCore.TestBase;
    using AngleSharp.Dom.Html;
    using AngleSharp.Parser.Html;
    using Microsoft.AspNetCore.Hosting;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Serialization;
    using Shouldly;
    using FFF.Test.DataAccess.Framework;
    using FFF.Test.Entity.Web;
    using YdmCodeArtCoreApplication.Tests.TestDatas;

    public abstract class MyAbpCodeArtCoreWebTestBase : AbpAspNetCoreIntegratedTestBase<Startup>
    {
        protected static readonly Lazy<string> ContentRootFolder;

        /// <summary>
        /// Initializes static members of the <see cref="MyAbpCodeArtCoreWebTestBase"/> class.
        /// 初始化的静态方法
        /// </summary>
        static MyAbpCodeArtCoreWebTestBase() => ContentRootFolder = new Lazy<string>(WebContentDirectoryFinder.CalculateContentRootFolder, true);

        protected MyAbpCodeArtCoreWebTestBase()
        {
            this.UsingDbContext(context => new TestDataBuilder(context).Build());
        }

        protected override IWebHostBuilder CreateWebHostBuilder()
        {
            return base
                .CreateWebHostBuilder()
                .UseContentRoot(ContentRootFolder.Value);
        }

        #region Get response

        protected async Task<T> GetResponseAsObjectAsync<T>(
            string url,
            HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
        {
            var strResponse = await this.GetResponseAsStringAsync(url, expectedStatusCode).ConfigureAwait(false);
            return JsonConvert.DeserializeObject<T>(strResponse, new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver()
            });
        }

        protected async Task<string> GetResponseAsStringAsync(
            string url,
            HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
        {
            var response = await this.GetResponseAsync(url, expectedStatusCode).ConfigureAwait(false);
            return await response.Content.ReadAsStringAsync();
        }

        protected async Task<HttpResponseMessage> GetResponseAsync(
            string url,
            HttpStatusCode expectedStatusCode = HttpStatusCode.OK)
        {
            var response = await this.Client.GetAsync(url).ConfigureAwait(true);
            response.StatusCode.ShouldBe(expectedStatusCode);
            return response;
        }

        #endregion

        #region UsingDbContext

        protected void UsingDbContext(Action<MyDbContext> action)
        {
            using (var context = base.IocManager.Resolve<MyDbContext>())
            {
                action(context);
                context.SaveChanges();
            }
        }

        protected T UsingDbContext<T>(Func<MyDbContext, T> func)
        {
            T result;

            using (var context = base.IocManager.Resolve<MyDbContext>())
            {
                result = func(context);
                context.SaveChanges();
            }

            return result;
        }

        protected async Task UsingDbContextAsync(Func<MyDbContext, Task> action)
        {
            using (var context = base.IocManager.Resolve<MyDbContext>())
            {
                await action(context).ConfigureAwait(false);
                await context.SaveChangesAsync(true).ConfigureAwait(false);
            }
        }

        protected async Task<T> UsingDbContextAsync<T>(Func<MyDbContext, Task<T>> func)
        {
            T result;

            using (var context = base.IocManager.Resolve<MyDbContext>())
            {
                result = await func(context).ConfigureAwait(false);
                context.SaveChanges();
            }

            return result;
        }

        #endregion

        #region ParseHtml

        protected IHtmlDocument ParseHtml(string htmlString)
        {
            return new HtmlParser().Parse(htmlString);
        }

        #endregion
    }
}